/**
 * 对象池
 */
package concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;

class Pool<T> {
    private int mSize;

    private volatile boolean[] mCheckedOutStates;

    private Semaphore mAvailable;

    private List<T> mObjects = new ArrayList<T>();

    public Pool(Class<T> classObject, int size) {
        mSize = size;
        mCheckedOutStates = new boolean[size];
        mAvailable = new Semaphore(size, true);

        try {
            for(int i = 0; i < size; ++i) {
                // Assumes a default constructor:
                mObjects.add(classObject.newInstance());
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public T checkOut() throws InterruptedException {
        mAvailable.acquire();
        return getObject();
    }

    private synchronized T getObject() {
        T ret = null;

        for(int i = 0; i < mSize; ++i) {
            if(!mCheckedOutStates[i]) {
                mCheckedOutStates[i] = true;
                ret = mObjects.get(i);
                break;
            }
        }

        return ret;
    }

    public void checkIn(T x) {
        if(releaseObject(x)) {
            mAvailable.release();
        }
    }

    private synchronized boolean releaseObject(T object) {
        int index = mObjects.indexOf(object);

        if(index == -1) {
            // Not in the list
            return false;
        }

        boolean ret = false;

        if(mCheckedOutStates[index]) {
            mCheckedOutStates[index] = false;
            ret = true;
        }

        return ret;
    }
}
